package cz.acies.genea.data.persist;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import cz.acies.data.persist.ModelObject;

public class GedPerson extends ModelObject implements Cloneable
{
	private static final long serialVersionUID = 1997109900568710920L;
	
	//private String id = null;
	private String projectId = null;
	private String firstName = null;
	private String lastName = null;
	private String maidenName = null;
	private String gender = "M"; 
	private Date birthDate = null; 
	private String birthPlace = null;
	private Date deathDate = null; 
	private String deathPlace = null;

	private GedFamily parents = null;
	private String descript = null;
	private String bookCode = null;
	
	private Map<String, GedFamily> partners = null;
	private Map<String, GedPerson> childern = null;
	
	public GedPerson() {
		this(null);
	}
	
	public GedPerson(String id) {
		partners = new LinkedHashMap<String, GedFamily>();
		childern = new LinkedHashMap<String, GedPerson>(); 
		this.id = id; 
	}
	
	public GedPerson(String id, Map<String, Object> data) {
		this(id);
		projectId = (String) data.get("projectId");
		firstName = (String) data.get("firstName");
		lastName = (String) data.get("lastName");
		maidenName = (String) data.get("maidenName");
		gender = (String) data.get("gender");
		birthDate = (Date) data.get("birthDate");
		birthPlace = (String) data.get("birthPlace");
		deathDate = (Date) data.get("deathDate");
		deathPlace = (String) data.get("deathPlace");
		if (data.containsKey("parents")) {
			String parentsId = (String) data.get("parents");
			if (parentsId != null) this.parents = new GedFamily(parentsId);
		}
		/*
		father = new GedPerson((String) data.get("FATHER_ID"));
		father.setFirstName((String) data.get("FATHER_NAME"));
		mather = new GedPerson((String) data.get("MATHER_ID")); 
		mather.setFirstName((String) data.get("MATHER_NAME"));
		*/
		descript = (String) data.get("DESCRIPT");
		bookCode = (String) data.get("BOOK_CODE");
	}
 
	// -----  -----------------------------------------------------------------
	
	@Override
	public String toString() {
		
		String s  = "{ " +
			"id: " + id + ", " +
			"name: " + getDisplayName() + ", " +
			//"firstName: " + firstName + ", " +
			//"lastName: " + lastName + ", " +
			//"maidenName: " + maidenName + ", " +
			//"gender: " + gender + ", " +
			"birthDate: " + birthDate + ", " +
			//"birthPlace: " + birthPlace + ", " +
			//"deathDate: " + deathDate + ", " +
			//"deathPlace: " + deathPlace + ", " +
			//"father: " + father + ", " +
			//"mather: " + mather + ", " +
			//"descript: " + descript + ", " + 
			//"code: " + bookCode + " " +
		"}";
		return s;
	}
	
	// -----  -----------------------------------------------------------------

	
	public String getFirstName() {
		return firstName;
	}
	
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public boolean hasFirstName() {
		return (firstName != null && firstName.trim().length() > 0);
	}

	public String getLastName() {
		return lastName;
	}
	
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	
	public boolean hasLastName() {
		return (lastName != null && lastName.trim().length() > 0);
	}

	public  String getDisplayName() {
		return 
			(hasFirstName() ? firstName : "") + " " + 
			(hasLastName() ? lastName : "") + " " +
			//(hasMaidenName() ? "("+maidenName+")" : "") + " " +
			""; 
	}
	
	/**
	 * Pohlví
	 * @return
	 */
	public String getGender() {
		return (hasGender()) ? gender : "M";
	}

	public boolean hasGender() {
		return (gender != null && (gender.equals("M") || gender.equals("F")));
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public boolean isFamale() {
		return (hasGender() && gender.equals("F"));
	}
	
	/**
	 * Rodné jméno
	 * @return
	 */
	public void setMaidenName(String maidenName) {
		this.maidenName = maidenName;
	}

	public String getMaidenName() {
		return maidenName;
	}

	public boolean hasMaidenName() {
		return (maidenName != null && maidenName.trim().length() > 0);
	}
	
	public Date getBirthDate() {
		return birthDate;
	}

	public boolean hasBirthDate() {
		return birthDate != null;
	}

	public void setBirthDate(Date  birthDate) {
		this.birthDate = birthDate;
	}

	public String getBirthPlace() {
		return birthPlace;
	}
	
	public boolean hasBirthPlace() {
		return birthPlace != null;
	}

	public void setBirthPlace(String birthPlace) {
		this.birthPlace = birthPlace;
	}

	public Date  getDeathDate() {
		return deathDate;
	}

	public boolean hasDeathDate() {
		return deathDate != null;
	}

	public void setDeathDate(Date deathDate) {
		this.deathDate = deathDate;
	}

	public String getDeathPlace() {
		return deathPlace;
	}
	
	public boolean hasDeathPlace() {
		return deathPlace != null;
	}

	public void setDeathPlace(String deathPlace) {
		this.deathPlace = deathPlace;
	}

	public String getDescript() {
		return descript;
	}

	public void setDescript(String descript) {
		this.descript = descript;
	}

	public String getBookCode() {
		return bookCode;
	}

	public void setBookCode(String code) {
		this.bookCode = code;
	}

	public String getProjectId() {
		return projectId;
	}

	public boolean hasProjectId() {
		return (projectId != null &&  projectId.startsWith("GE.P."));
	}

	public void setProjectId(String projectId) {
		this.projectId = projectId;
	}

	public Map<String, GedFamily> getPartners() {
		return partners;
	}
	
	public void addPartner(GedFamily family) {
		if (partners == null) partners = new LinkedHashMap<String, GedFamily>();
		if (family == null || !family.hasId()) return;
		partners.put(family.getId(), family);
	}
	
	public void setPartners(Map<String, GedFamily> map) {
		this.partners = map;
	}

	public void setPartners(List<GedFamily> list) {
		if (partners == null) partners = new LinkedHashMap<String, GedFamily>(); 
		else partners.clear();
		for (GedFamily family : list) {
			addPartner(family);
		}
	}

	public void setFather(GedPerson father) {
		if (!hasParents()) { this.parents = new GedFamily(); }
		this.parents.setMan(father);
	}
	
	public GedPerson getFather() {
		return (this.hasParents()) ? this.getParents().getMan() : null;
	}
	
	public boolean hasFather() {
		return (this.hasParents()) ? this.getParents().hasMan() : false;
	}
	
	public GedPerson getMather() {
		return (this.hasParents()) ? this.getParents().getWoman() : null;
	}
	
	public void setMather(GedPerson mather) {
		if (!hasParents()) { this.parents = new GedFamily(); }
		this.parents.setWoman(mather);
	}
	
	public boolean hasMather() {
		return (this.hasParents()) ? this.getParents().hasWoman() : false;
	}
	
	public GedFamily getParents() {
		return parents;
	}

	public boolean hasParents() {
		return (parents instanceof GedFamily);
	}

	public void setParents(GedFamily parents) {
		this.parents = parents;
	}

	public List<GedPerson> getChildern() {
		return new ArrayList<GedPerson>(childern.values());
	}

	public void setChildern(Map<String, GedPerson> map) {
		this.childern = map;
	}

	public void setChildern(List<GedPerson> list) {
		if (childern == null) childern = new LinkedHashMap<String, GedPerson>(); 
		else childern.clear();
		for (GedPerson person : list) {
			addChild(person);
		}
		//this.childern = childern;
	}
	
	public void addChild(GedPerson child) {
		if (childern == null) childern = new LinkedHashMap<String, GedPerson>();
		if (child == null || !child.hasId()) return;
		childern.put(child.getId(), child);
	}
	
	// -----  -----------------------------------------------------------------
	
	public Object clone() throws CloneNotSupportedException {
		Object clone = super.clone();
		assert clone instanceof GedPerson;
		
		((GedPerson) clone).setId(this.id);
		
		((GedPerson) clone).setProjectId(this.projectId);
		((GedPerson) clone).setFirstName(this.firstName);
		((GedPerson) clone).setLastName(this.lastName);
		((GedPerson) clone).setMaidenName(this.maidenName);
		((GedPerson) clone).setGender(this.gender); 
		((GedPerson) clone).setBirthDate(this.birthDate); 
		((GedPerson) clone).setBirthPlace(this.birthPlace);
		((GedPerson) clone).setDeathDate(this.deathDate); 
		((GedPerson) clone).setDeathPlace(this.deathPlace);
		((GedPerson) clone).setDescript(this.descript);
		((GedPerson) clone).setBookCode(this.bookCode);
		
		((GedPerson) clone).setParents((parents != null) ? (GedFamily) parents.clone()  : null);
		((GedPerson) clone).setPartners((partners != null) ? 
			(Map<String, GedFamily>)((LinkedHashMap<String, GedFamily>) partners).clone() : null);
		((GedPerson) clone).setChildern((childern != null) ? 
			(Map<String, GedPerson>)((LinkedHashMap<String, GedPerson>) childern).clone() : null);
		
		return clone;
	}

}
